import json
import re

from django import http
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import EmptyPage, Paginator
from django.db import DatabaseError
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from django_redis import get_redis_connection

from apps.areas.models import Address
from apps.orders.models import OrderInfo
from apps.shoppingcarts.utils import merge_cart_cookie_to_redis
from apps.users.models import Users
from apps.users.response_code import RETCODE
from utils import constants
from utils.views import LoginRequiredJSONMixin


class RegisterView(View):
    """
    注册视图
    """

    def get(self, request):
        return render(request, 'register.html')

    def post(self, request):
        """
        1.接收参数
        2.校验参数
        3.查询users
        4.保存到数据库
        5.返回响应重定向到主页
        :param request:
        :return:
        """
        # 接收参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')
        allow = request.POST.get('allow')
        sms_code = request.POST.get('sms_code')

        # 校验参数
        if not all([username, password, password2, mobile, allow]):
            return http.HttpResponse('请填写完整信息')

        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return http.HttpResponseBadRequest('请填写5-20位字符的用户名(数字、字母、下划线)')

        if not re.match(r'^[a-zA-Z0-9_]{8,20}$', password):
            return http.HttpResponseBadRequest('请填写8-20位字符的密码(数字、字母、下划线)')

        if password != password2:
            return http.HttpResponseBadRequest('两次输入的密码不一致')

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('请输入正确的手机号码')
        # # 连接redis
        # redis_conn = get_redis_connection('code')
        # send_sms_flag = redis_conn.get('sms_%s' % mobile)
        # if send_sms_flag != sms_code:
        #     print('短信验证码错误')
        #     return render(request, 'register.html', {'code': RETCODE.SMSCODERR, 'errmsg': '短信验证码错误'})

        redis_conn = get_redis_connection('code')
        sms_code_saved = redis_conn.get('sms_%s' % mobile)
        if sms_code_saved is None:
            return render(request, 'register.html', {'sms_code_errmsg': '无效的短信验证码'})
        if sms_code != sms_code_saved.decode():
            return render(request, 'register.html', {'sms_code_errmsg': '输入短信验证码有误'})
        if allow != 'on':
            return http.HttpResponseBadRequest('请同意用户协议')

        try:
            # 创建用户对象
            user = Users.objects.create_user(username=username, password=password, mobile=mobile)
        except DatabaseError:
            return render(request, 'register.html', {'errmsg': '注册失败'})

        # 保持状态
        login(request, user)
        # 定义一个响应对象
        response = redirect(reverse('index:index'))
        # 在响应对象中设置cookie值为用户名
        response.set_cookie('username', username)

        # 返回响应对象
        return response


class LoginView(View):
    """
    登录视图
    """

    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        """
        获取参数
        校验参数
        查询是否有该用户信息&对比密码
        返回信息
        :param request:
        :return:
        """

        username = request.POST.get('username')  # 用户名 username/mobile
        password = request.POST.get('password')  # 密码
        remembered = request.POST.get('remembered')  # 是否记住登录

        if not all([username, password]):
            return render(request, 'login.html', {'account_errmsg': '请填写用户名或密码'})

        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return render(request, 'login.html', {'account_errmsg': '请填写5-20位字符的用户名(数字、字母、下划线)'})

        if not re.match(r'^[a-zA-Z0-9_]{8,20}$', password):
            return render(request, 'login.html', {'account_errmsg': '请填写8-20位的密码(数字、字母、下划线)'})
        # 判断是否需要记住用户
        if remembered != 'on':
            # 浏览器关闭后清除用户信息
            request.session.set_expiry(0)
            print('-------------------0')

        # 保存用户信息两周
        request.session.set_expiry(None)

        # 检查是否有该用户
        user = authenticate(username=username, password=password)

        if not user:
            return render(request, 'login.html', {'account_errmsg': '用户名或密码错误'})

        login(request, user)

        next = request.GET.get('next')
        if next:
            response = redirect(next)
        else:
            # 响应信息
            response = redirect(reverse('index:index'))
        # 将用户名存入到cookie中
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        response = merge_cart_cookie_to_redis(request, user, response)

        return response


class UsernameCountView(View):
    """
    查username是否已经在数据库中存在该数据
    """

    def get(self, request, username):
        count = Users.objects.filter(username=username).count()

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': None, 'count': count})


class MobileCountView(View):
    """
    查询mobile是否已经在数据库中存在该数据
    """

    def get(self, request, mobile):
        count = Users.objects.filter(mobile=mobile).count()

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': None, 'count': count})


class LogoutView(View):
    """
    退出
    """

    @staticmethod
    def get(request):
        #
        logout(request)

        response = redirect(reverse('index:index'))

        response.delete_cookie('username')

        return response


class UserCenterView(LoginRequiredMixin, View):
    """用户中心"""

    def get(self, request):
        """提供个人信息界面"""

        context = {
            'username': request.user.username,
            'mobile': request.user.mobile,
            'email': request.user.email,
            'email_active': request.user.email_active,

        }
        return render(request, 'base_user_center.html', context=context)


class AddressView(LoginRequiredMixin, View):

    def get(self, request):
        # 展示该用户的所有收货地址(没有进行逻辑删除的)
        user_address = Address.objects.filter(user=request.user, is_deleted=False)
        address_dict_list = []
        for address in user_address:
            address_dict = {
                "id": address.id,  # 收货地址id
                "title": address.title,  # 收货人
                "receiver": address.receiver,  # 收货人
                "province": address.province.name,  # 收货省份
                "province_id": address.province_id,  # 省份id
                "city": address.city.name,  # 市
                "city_id": address.city_id,  # 市id
                "district": address.district.name,  # 县
                "district_id": address.district_id,  # 县id
                "place": address.place,  # 详细地址
                "mobile": address.mobile,  # 手机号码
                "tel": address.tel,  # 固定电话
                "email": address.email,  # 邮箱
            }
            address_dict_list.append(address_dict)
        context = {
            'default_address_id': request.user.default_address_id,  # 默认收货地址id
            'addresses': address_dict_list,
        }

        return render(request, 'base_user_center_site.html', context=context)


class UpdatePasswordView(LoginRequiredJSONMixin, View):
    """修改密码"""

    def get(self, request):
        return render(request, 'base_user_center_pass.html')

    def post(self, request):
        # 获取参数
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        new_password2 = request.POST.get('new_password2')

        # 校验参数
        if not all([old_password, new_password, new_password2]):
            return http.HttpResponseBadRequest('请填写完整信息')

        if new_password != new_password2:
            return http.HttpResponseBadRequest("两次输入的新密码不一致")

        try:
            # 获取当前用户对象
            user = Users.objects.get(username=request.user.username)
            # 校验密码
            if not (user and user.check_password(old_password)):
                return render(request, 'user_center_pass.html', {'origin_password_errmsg': '原密码输入有误'})
            # 设置新密码
            user.set_password(new_password)
            user.save()

        except:
            return render(request, 'user_center_pass.html', {'errmsg': '修改密码失败'})
        # 退出登录
        logout(request)
        response = redirect(reverse('users:login'))
        response.delete_cookie('username')
        return response


class MyOrderView(LoginRequiredMixin, View):

    def get(self, request, page_num):
        user = request.user
        orders = user.orderinfo_set.all().order_by('-create_time')
        # print(orders)
        for order in orders:

            order.pay_method_name = OrderInfo.PAY_METHOD_CHOICES[order.pay_method - 1][1]
            order.status_name = OrderInfo.ORDER_STATUS_CHOICES[order.status - 1][1]

            order_goods = order.skus.all()

            order.sku_list = []
            for goods in order_goods:
                sku = goods.sku
                sku.count = goods.count
                sku.amount = goods.count * goods.price
                order.sku_list.append(sku)

        page_num = int(page_num)
        try:
            paginator = Paginator(orders, constants.ORDERS_LIST_LIMIT)
            page_orders = paginator.page(page_num)
            total_page = paginator.num_pages
        except:
            return http.HttpResponseBadRequest('订单不存在')

        context = {
            'page_orders': page_orders,
            'page_num': page_num,
            'total_page': total_page,
        }

        return render(request, 'user_center_order.html', context=context)
